use rust_mcp_sdk::macros::{mcp_tool, JsonSchema};
use rust_mcp_sdk::schema::{schema_utils::CallToolError, CallToolResult, TextContent};
use serde_json::json;

use crate::tms_client::TmsClient;

#[mcp_tool(
    name = "create_transport_plan",
    title = "Create Transport Plan",
    description = "Create a new transport plan that assigns orders to vehicles and drivers with planned execution times.",
    destructive_hint = true,
    idempotent_hint = false,
    open_world_hint = false,
    read_only_hint = false
)]
#[derive(serde::Deserialize, serde::Serialize, Clone, Debug, JsonSchema)]
pub struct CreateTransportPlanTool {
    /// Plan name
    pub name: String,
    /// Plan description
    pub description: String,
    /// Order IDs to include in the plan
    pub order_ids: Vec<String>,
    /// Vehicle ID to assign
    pub vehicle_id: String,
    /// Driver ID to assign
    pub driver_id: String,
    /// Planned start time (Unix timestamp)
    pub planned_start_time: i64,
    /// Planned end time (Unix timestamp)
    pub planned_end_time: i64,
}

impl CreateTransportPlanTool {
    pub async fn run_tool(params: Self, client: &mut TmsClient) -> Result<CallToolResult, CallToolError> {
        match client.create_transport_plan(
            params.name,
            params.description,
            params.order_ids,
            params.vehicle_id,
            params.driver_id,
            params.planned_start_time,
            params.planned_end_time,
        ).await {
            Ok(plan) => {
                let response = json!({
                    "message": "Transport plan created successfully",
                    "plan": format!("{:?}", plan)
                });
                Ok(CallToolResult::text_content(vec![TextContent::from(response.to_string())]))
            },
            Err(e) => Err(CallToolError::new(std::io::Error::new(std::io::ErrorKind::Other, format!("Failed to create transport plan: {}", e)))),
        }
    }
}

#[mcp_tool(
    name = "list_transport_plans",
    title = "List Transport Plans",
    description = "List transport plans with pagination and status filtering. Status values: 0=Pending, 1=Approved, 2=InProgress, 3=Completed, 4=Cancelled.",
    destructive_hint = false,
    idempotent_hint = true,
    open_world_hint = false,
    read_only_hint = true
)]
#[derive(serde::Deserialize, serde::Serialize, Clone, Debug, JsonSchema)]
pub struct ListTransportPlansTool {
    /// Page number for pagination (default: 1)
    #[serde(default = "default_page")]
    pub page: i32,
    /// Number of items per page (default: 10, max: 100)
    #[serde(default = "default_page_size")]
    pub page_size: i32,
    /// Filter by status (optional): 0=Pending, 1=Approved, 2=InProgress, 3=Completed, 4=Cancelled
    pub status: Option<i32>,
}

fn default_page() -> i32 { 1 }
fn default_page_size() -> i32 { 10 }

impl ListTransportPlansTool {
    pub async fn run_tool(params: Self, client: &mut TmsClient) -> Result<CallToolResult, CallToolError> {
        match client.list_transport_plans(params.page, params.page_size, params.status.unwrap_or(0)).await {
            Ok(plans) => {
                let response = json!({
                    "plans": format!("{:?}", plans),
                    "page": params.page,
                    "page_size": params.page_size,
                    "total": plans.total
                });
                Ok(CallToolResult::text_content(vec![TextContent::from(response.to_string())]))
            },
            Err(e) => Err(CallToolError::new(std::io::Error::new(std::io::ErrorKind::Other, format!("Failed to list transport plans: {}", e)))),
        }
    }
}

#[mcp_tool(
    name = "get_transport_plan",
    title = "Get Transport Plan",
    description = "Get detailed information about a specific transport plan by ID.",
    destructive_hint = false,
    idempotent_hint = true,
    open_world_hint = false,
    read_only_hint = true
)]
#[derive(serde::Deserialize, serde::Serialize, Clone, Debug, JsonSchema)]
pub struct GetTransportPlanTool {
    /// Transport plan ID
    pub id: String,
}

impl GetTransportPlanTool {
    pub async fn run_tool(params: Self, client: &mut TmsClient) -> Result<CallToolResult, CallToolError> {
        match client.get_transport_plan(params.id).await {
            Ok(plan) => {
                Ok(CallToolResult::text_content(vec![TextContent::from(format!("{:?}", plan))]))
            },
            Err(e) => Err(CallToolError::new(std::io::Error::new(std::io::ErrorKind::Other, format!("Failed to get transport plan: {}", e)))),
        }
    }
}

#[mcp_tool(
    name = "optimize_route",
    title = "Optimize Route",
    description = "Optimize the route for a set of orders and vehicle to minimize distance, time, cost, or fuel consumption. Optimization objectives: 0=Distance, 1=Time, 2=Cost, 3=Fuel.",
    destructive_hint = false,
    idempotent_hint = false,
    open_world_hint = false,
    read_only_hint = false
)]
#[derive(serde::Deserialize, serde::Serialize, Clone, Debug, JsonSchema)]
pub struct OptimizeRouteTool {
    /// Order IDs to optimize
    pub order_ids: Vec<String>,
    /// Vehicle ID for the route
    pub vehicle_id: String,
    /// Optimization objective (0=Distance, 1=Time, 2=Cost, 3=Fuel)
    pub objective: i32,
}

impl OptimizeRouteTool {
    pub async fn run_tool(params: Self, client: &mut TmsClient) -> Result<CallToolResult, CallToolError> {
        match client.optimize_route(params.order_ids, params.vehicle_id, params.objective).await {
            Ok(optimized_route) => {
                let response = json!({
                    "message": "Route optimized successfully",
                    "optimized_route": format!("{:?}", optimized_route)
                });
                Ok(CallToolResult::text_content(vec![TextContent::from(response.to_string())]))
            },
            Err(e) => Err(CallToolError::new(std::io::Error::new(std::io::ErrorKind::Other, format!("Failed to optimize route: {}", e)))),
        }
    }
}